package com.huixuebao.api.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huixuebao.api.dto.CategoryDTO;
import com.huixuebao.api.dto.CourseDTO;
import com.huixuebao.api.dto.PayAmountComplexResult;
import com.huixuebao.api.entity.BaseDivision;
import com.huixuebao.api.entity.CourseEntity;
import com.huixuebao.api.entity.MechanismEntity;
import com.huixuebao.api.mapper.BaseDivisionMapper;
import com.huixuebao.api.mapper.CourseMapper;
import com.huixuebao.api.mapper.MechanismMapper;
import com.huixuebao.api.service.rpc.CategoryService;
import com.huixuebao.api.service.CourseService;
import com.huixuebao.api.util.pay.PayUtil;
import com.huixuebao.common.bean.ApiResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @version 1.0
 * @date 2020-11-16 21:45
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, CourseEntity> implements CourseService {

    @Autowired
    MechanismMapper mechanismMapper;

    @Autowired
    BaseDivisionMapper baseDivisionMapper;

    @Autowired
    CourseMapper courseMapper;

    @Autowired
    CategoryService categoryService;

    @Override
    public ApiResult<List<CourseDTO>> getAllCourse(String cityId, Double longitude, Double latitude, Integer distance, Double minPrice,
                                                   Double maxPrice, String categoryId, String brand,
                                                   String courseName) {
        List<MechanismEntity> allSatisfiedMerchants = new ArrayList<>();
        if (StrUtil.isNotBlank(cityId)) {
            List<String> allCityIds = getChilds(cityId);
            allCityIds.add(cityId);
            allSatisfiedMerchants = mechanismMapper.selectList(new LambdaQueryWrapper<MechanismEntity>()
                    .in(MechanismEntity::getCityId, allCityIds)
                    .like(StrUtil.isNotBlank(brand), MechanismEntity::getBrand, brand));
        } else {
            List<MechanismEntity> allMerchants = mechanismMapper.selectList(new LambdaQueryWrapper<MechanismEntity>()
                    .like(StrUtil.isNotBlank(brand), MechanismEntity::getBrand, brand));
            // 找到全部距离上小于distance的机构
            for (MechanismEntity mechanismEntity : allMerchants) {
                if (StrUtil.isNotBlank(mechanismEntity.getAxisX()) && StrUtil.isNotBlank(mechanismEntity.getAxisY())) {
                    double d = getDistanceFromTwoPoints(latitude, longitude, Double.parseDouble(mechanismEntity.getAxisX()), Double.parseDouble(mechanismEntity.getAxisY()));
                    if (d <= distance) {
                        allSatisfiedMerchants.add(mechanismEntity);
                    }
                }
            }
        }
        // 找出满足条件的机构关联的全部课程
        List<CourseDTO> result = new ArrayList<>();
        List<String> userNumbers = allSatisfiedMerchants.stream().map(MechanismEntity::getUserNubmer).collect(Collectors.toList());

        //课程分类id
        List<String> categoryIds = null;
        if (StrUtil.isNotBlank(categoryId)) {
            ApiResult<List<CategoryDTO>> apiResult = categoryService.listAllCategoryByPid(categoryId);
            List<CategoryDTO> categories = apiResult.getData();
            categoryIds = categories.stream().map(CategoryDTO::getId).collect(Collectors.toList());
        }
        if (CollUtil.isNotEmpty(userNumbers)) {
            this.list(new LambdaQueryWrapper<CourseEntity>().in(CourseEntity::getMechanismNo, userNumbers)
                    .ge(ObjectUtil.isNotNull(minPrice), CourseEntity::getCoursePrice, minPrice)
                    .lt(ObjectUtil.isNotNull(maxPrice), CourseEntity::getCoursePrice, maxPrice)
                    .in(StrUtil.isNotBlank(categoryId), CourseEntity::getCategoryId, categoryIds)
                    .like(StrUtil.isNotBlank(courseName), CourseEntity::getCourseName, courseName))
                    .forEach(entity -> {
                        CourseDTO courseDTO = new CourseDTO();
                        MechanismEntity mechanismEntity = mechanismMapper.selectOne(new LambdaQueryWrapper<MechanismEntity>().eq(MechanismEntity::getUserNubmer, entity.getMechanismNo()));

                        /**
                         * 在课程原价的基础上增加20%
                         */
                        BeanUtil.copyProperties(entity, courseDTO);
                        BigDecimal coursePrice = entity.getCoursePrice();
                        //BigDecimal cousrPrices = coursePrice.add(coursePrice.multiply(new BigDecimal("0.2"))).setScale(2, BigDecimal.ROUND_HALF_UP);
                        courseDTO.setCoursePrice(coursePrice);
                        courseDTO.setMerchantName(mechanismEntity.getName());
                        result.add(courseDTO);
                    });
        }
        ApiResult apiResult = new ApiResult();
        apiResult.setData(result);
        return apiResult;
    }

    /**
     * 根据课程id查询出理赔额度
     * @param courseNo
     * @return
     */
    @Override
    public ApiResult<PayAmountComplexResult> getCoursePrice(String courseNo) {
        ApiResult apiResult = new ApiResult();
            CourseEntity entity = courseMapper.selectOne(new LambdaQueryWrapper<CourseEntity>()
                    .eq(CourseEntity::getCourseNo,courseNo));
        PayAmountComplexResult payAmountComplexResult = PayUtil.calcPayAmount(entity.getCoursePrice(), entity.getSettlePrice());
        apiResult.setData(payAmountComplexResult);
        return apiResult;
    }

    private List<String> getChilds(String cityId) {
        List<String> result = new ArrayList<>();
        List<String> childs = baseDivisionMapper.selectList(new LambdaQueryWrapper<BaseDivision>().eq(BaseDivision::getPId, cityId)).stream().map(BaseDivision::getId).collect(Collectors.toList());
        result.addAll(childs);
        childs.stream().forEach(child -> {
            List<String> list = baseDivisionMapper.selectList(new LambdaQueryWrapper<BaseDivision>().eq(BaseDivision::getPId, child)).stream().map(BaseDivision::getId).collect(Collectors.toList());
            result.addAll(list);
        });
        return result;
    }

    private double getDistanceFromTwoPoints(double lat_a, double lng_a, double lat_b, double lng_b) {
        Double PI = Math.PI;
        Double PK = 180 / PI;

        double t1 = Math.cos(lat_a / PK) * Math.cos(lng_a / PK) * Math.cos(lat_b / PK) * Math.cos(lng_b / PK);
        double t2 = Math.cos(lat_a / PK) * Math.sin(lng_a / PK) * Math.cos(lat_b / PK) * Math.sin(lng_b / PK);
        double t3 = Math.sin(lat_a / PK) * Math.sin(lat_b / PK);

        double tt = Math.acos(t1 + t2 + t3);

        return 6366000 * tt;
    }
}